import numpy as np
import json
import os
import matplotlib.pyplot as plt
from sklearn.metrics import accuracy_score,confusion_matrix


def convert_to_one_hot(data):
    # 转化独热向量
    data=np.array(data)
    C=data.max()+1    # 类别
    return np.eye(C)[data.reshape(-1)]


def getJsonData(json_path,feature_name):
    # 获取特征数据
    with open(json_path,"r",encoding="utf-8") as f:
        d=json.load(f)
        features=[]
        for name in feature_name:
            features.append(d[name])
    return features


def getAllData(json_dir,feature_name,label2id):
    # 获取所有特征数据
    files=os.listdir(json_dir)  # 获取目录下所有文件名
    features=[]
    labels=[]
    for file in files:
        word_label=file.rstrip(".json")      # 获取标签
        feature=getJsonData(os.path.join(json_dir,file),feature_name)
        features.extend(feature)
        labels.extend([label2id[word_label]]*len(feature))
    return features,labels


def plot_confusion_matrix(cm, labels_name, title):
    """
    绘制混淆矩阵
    :param cm: 混淆矩阵
    :param labels_name: 标签名字
    :param title: 标题
    :return:
    """
    cm_scale = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]    # 归一化
    plt.imshow(cm_scale, interpolation='nearest',
               cmap=plt.cm.Blues)    # 在特定的窗口上显示图像
    plt.title(title)    # 图像标题
    plt.colorbar()
    num_local = np.array(range(len(labels_name)))
    plt.xticks(num_local, labels_name, rotation=90)    # 将标签印在x轴坐标上
    plt.yticks(num_local, labels_name)    # 将标签印在y轴坐标上
    plt.ylabel('True label')
    plt.xlabel('Predicted label')
    for i in range(cm.shape[0]):
        for j in range(cm.shape[1]):
            plt.text(j-0.1,i,cm[i,j])


def getAccuracy(labels,prediction):
    # 正确率
    correct_pred = accuracy_score(labels,prediction)
    return correct_pred


def getConfusionMatrix(labels,prediction):
    matrix=confusion_matrix(labels,prediction)
    return matrix


def saveEpochFigure(draw_object,x_length,title,label_name,
                    legend_name,save_path):
    plt.figure(title)
    x = list(range(x_length))
    plt.plot(x, draw_object[0], "r,-", label=legend_name[0])
    plt.plot(x, draw_object[1], "b,-", label=legend_name[1])
    plt.xlabel(label_name[0])
    plt.ylabel(label_name[1])
    plt.legend()
    plt.savefig(save_path)
    plt.show()


def softmax_2D(matrix):
    if matrix.ndim!=2:
        raise ValueError("dims should be 2D!")
    matrix_shape=matrix.shape
    matrix_row_max=np.max(matrix,axis=-1).reshape(matrix_shape[0],1)
    matrix=matrix-matrix_row_max    # 每一行减去最大值，不这样处理容易出现INF
    matrix_exp=np.exp(matrix)
    matrix_exp_row_sum=np.sum(matrix_exp,axis=-1).reshape(matrix_shape[0],1)
    softmax=matrix_exp/matrix_exp_row_sum
    return softmax

